package com.urbanflow.vinci.parcourt;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.urbanflow.vinci.controler.ArretManager;
import com.urbanflow.vinci.controler.HoraireManager;
import com.urbanflow.vinci.controler.LigneManager;
import com.urbanflow.vinci.main.Arret;
import com.urbanflow.vinci.main.Horaire;
import com.urbanflow.vinci.main.Ligne;

public class Graphe {
	private List<Graphe> mesLiaisons;
	private Arret noeud;
	
	public Graphe(Arret unNoeud) {
		setNoeud(unNoeud);
		unNoeud.setPoint(this);
		mesLiaisons = new ArrayList<Graphe>();
	}
	public Graphe(Arret unNoeud, Graphe unGraphe) {
		setNoeud(unNoeud);
		unNoeud.setPoint(this);
		mesLiaisons = new ArrayList<Graphe>();
		mesLiaisons.add(unGraphe);
	}

	public List<Graphe> getMesLiaisons() {
		return mesLiaisons;
	}

	public void setMesLiaisons(List<Graphe> mesLiaisons) {
		this.mesLiaisons = mesLiaisons;
	}

	public Arret getNoeud() {
		return noeud;
	}

	public void setNoeud(Arret noeud) {
		this.noeud = noeud;
	}
	
	public List<Arret> construireRecursif(List<Arret> arretEncoreDisponible,Map<Integer,Graphe> grapheConstruit) {
		List<Arret> arretsPossible = ArretManager.getInstance().donnerlesArretsSuivant(noeud);
		List<Arret> arretsUtiliser = new ArrayList<Arret>();
		for(Arret unArret: arretsPossible) {
			Graphe leGraphe = grapheConstruit.get(unArret.getIdArret());
			if(leGraphe != null) {
				if(! mesLiaisons.contains(leGraphe)) 
					mesLiaisons.add(leGraphe);
			} else {
				arretsUtiliser.add(noeud);
				Graphe sousBranche = new Graphe(unArret);
				grapheConstruit.put(unArret.getIdArret(), sousBranche);
				mesLiaisons.add(sousBranche);
				sousBranche.construireRecursif(arretEncoreDisponible, grapheConstruit);
			}
		}
		return arretsUtiliser;
	}
	
	public Graphe retournerGrapheDepart(Arret arretDepart, Graphe arrive) {
		if(noeud == arretDepart)  {
			return this;
		}
		for(Graphe leGraphe : mesLiaisons) {
			if(leGraphe != arrive) {
				Graphe leRetour = leGraphe.retournerGrapheDepart(arretDepart, this);
				if(leRetour != null)
					return leRetour;
			}
		}
		return null;
	}
	
	public Branche construireArbre(Arret fin, Graphe arrive) {
		Branche enCours = new Branche(noeud);
		if(noeud == fin) {
			enCours.setaGarder(true);
			return enCours;
		}
		for(Graphe unGraphe : mesLiaisons) {
			if(unGraphe != arrive) {
				Branche sousBranche = unGraphe.construireArbre(fin, this);
				if(sousBranche != null) {
					enCours.ajouterSousBranche(sousBranche);
				}
			}
		}
		if(enCours.possedeParcours()) {
			return enCours;
		}
		// TODO Auto-generated method stub
		return null;
	}

//	public Chemin construireArbre(Arret fin, Graphe arrive, Date maDateArrive, Map<String,Chemin> mesCheminsVerifier, Chemin cheminEnCours, List<Chemin>) {
//		Horaire monHoraire = HoraireManager.getInstance().retournerHoraire(cheminEnCours.getMoyen(), noeud, maDateArrive);
//		cheminEnCours.setArrive(noeud);
//		cheminEnCours.setLhoraire(monHoraire);
//		StringBuffer id = new StringBuffer();
//		
//		id.append(cheminEnCours.getDepart().getNomArret()).append("-").append(noeud.getNomArret());
//		String idRe = id.toString();
//		Chemin cheminVerifie = mesCheminsVerifier.get(idRe);
//		if(cheminVerifie == null) {
//			mesCheminsVerifier.put(idRe, cheminEnCours);
//		} else {
//			if(cheminVerifie.getLhoraire().getDate().after(monHoraire.getDate())) {
//				mesCheminsVerifier.put(idRe, cheminVerifie);
//			}
//		}
//		
//		Branche enCours = new Branche(noeud);
//		if(noeud == fin) {
//			
//			return enCours;
//		}
//		for(Graphe unGraphe : mesLiaisons) {
//			if(unGraphe != arrive) {
//				Branche sousBranche = unGraphe.construireArbre(fin, this);
//				if(sousBranche != null) {
//					enCours.ajouterSousBranche(sousBranche);
//				}
//			}
//		}
//		if(enCours.possedeParcours()) {
//			return enCours;
//		}
//		// TODO Auto-generated method stub
//		return null;
//	}

	public List<Chemin> getAllChemin(Date dateDepart, Chemin unChemin) {
		List<Chemin> maListe = new ArrayList<Chemin>();
		if(unChemin != null && noeud == unChemin.getDepart()) 
			return maListe;
		for(Graphe unGraphe : mesLiaisons) {
			List<Ligne> mesLignes = ArretManager.getInstance().donnerLignesEntre(noeud, unGraphe.getNoeud());
			Chemin best = null;
//			for(Ligne maLigne : mesLignes) {
//				best = new Chemin(noeud,unGraphe,null);
//				best.setCheminPrecedent(unChemin);
//				best.setMoyen(maLigne);
//				maListe.add(best);
//			}
			
			Horaire bestHoraire = null;
			for(Ligne maLigne : mesLignes ) {
				Horaire monHoraireArrive = HoraireManager.getInstance().retournerHoraire(maLigne, this.getNoeud(), LigneManager.getInstance().donnerArretSuivant(maLigne,this.getNoeud()), dateDepart);
			
					best = new Chemin(noeud,unGraphe,monHoraireArrive);
					best.setCheminPrecedent(unChemin);
					best.setMoyen(maLigne);
					bestHoraire = monHoraireArrive;
			
			}
			if(best != null) {
				maListe.add(best);
			}
		}		
		return maListe;
		
	}}
